package mysql

import (
	"context"
	"errors"

	v1 "gitee.com/youkelike/ziam/zapi/apiserver/v1"
	metav1 "gitee.com/youkelike/ziam/zapi/meta/v1"
	"gitee.com/youkelike/ziam/zcode/zcode"
	"gitee.com/youkelike/ziam/zerrors"
	"gitee.com/youkelike/ziam/zorm/store"
	"gitee.com/youkelike/ziam/zutils/gormutil"
	"gorm.io/gorm"
)

func newUserStore(d *dataStore) store.UserStore {
	return &userStore{db: d.db}
}

type userStore struct {
	db *gorm.DB
}

func (s *userStore) Create(ctx context.Context, user *v1.User, opts metav1.CreateOptions) error {
	// err := s.db.Exec("insert into user (username, phone, createAt) values (?,?,?)", user.Username, user.Phone, user.CreateAt.Format("2006-01-02 15:04:05")).Error
	// zlog.Errorw("%s", err)

	return s.db.Create(&user).Error
}

func (s *userStore) Update(ctx context.Context, user *v1.User, opts metav1.UpdateOptions) error {
	return s.db.Save(user).Error
}

func (s *userStore) Delete(ctx context.Context, username string, opts metav1.DeleteOptions) error {
	pol := newPolicies(&dataStore{s.db})
	if err := pol.DeleteByUser(ctx, username, opts); err != nil {
		return err
	}

	if opts.Unscoped {
		s.db = s.db.Unscoped()
	}

	err := s.db.Where("name=?", username).Delete(&v1.User{}).Error
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return zerrors.WithCode(zcode.ErrDatabase, err.Error())
	}

	return nil
}

func (s *userStore) DeleteCollection(ctx context.Context, usernames []string, opts metav1.DeleteOptions) error {
	pol := newPolicies(&dataStore{s.db})
	if err := pol.DeleteCollectionByUser(ctx, usernames, opts); err != nil {
		return err
	}

	if opts.Unscoped {
		s.db = s.db.Unscoped()
	}

	return s.db.Where("name in (?)", usernames).Delete(&v1.User{}).Error
}

func (s *userStore) List(ctx context.Context, opts metav1.ListOptions) (*v1.UserList, error) {
	ret := &v1.UserList{}
	ol := gormutil.GetLimitAndOffset(opts.Offset, opts.Limit)
	d := s.db.Where("status = 1").
		Offset(ol.Offset).
		Limit(ol.Limit).
		Order("id desc").
		Find(&ret.Items).
		Offset(-1).
		Limit(-1).
		Count(&ret.TotalCount)

	return ret, d.Error
}

func (s *userStore) Get(ctx context.Context, username string, opts metav1.GetOptions) (user *v1.User, err error) {
	err = s.db.Where("name=? and status=1", username).First(&user).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, zerrors.WithCode(zcode.ErrUserNotFound, err.Error())
		}
		return nil, zerrors.WithCode(zcode.ErrDatabase, err.Error())
	}
	return user, nil

	// if err := s.db.Where("username=?", username).First(user).Error; err != nil {
	// 	if errors.Is(err, gorm.ErrRecordNotFound) {
	// 		return nil, zerrors.WithCode(zcode.ErrUserNotFound, err.Error())
	// 	}
	// 	return nil, zerrors.WithCode(zcode.ErrDatabase, err.Error())
	// }

	// return
}
